using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using OkTool.IO.File;
using OkTool.Util;

namespace OkTool.IO
{
    public class FileUtil
    {
        /// <summary>
        /// 是否为windows环境
        /// </summary>
        /// <returns></returns>
        public static bool IsWindows()
        {
            return FileNameUtil.WINDOWS_SEPARATOR == Path.DirectorySeparatorChar;
        }

        /// <summary>
        /// 文件是否为空
        /// <para>目录:里面没有文件时为空  文件: 文件大小为0为空</para>
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public static bool IsEmpty(FileSystemInfo file)
        {
            if (file == null || file.Exists == false)
            {
                return true;
            }

            if (file.Attributes.HasFlag(FileAttributes.Directory))
            {
                var subFiles = Directory.GetFileSystemEntries(file.FullName);
                return subFiles.Length == 0;
            }

            if (file.Attributes.HasFlag(FileAttributes.Normal) || file.Attributes.HasFlag(FileAttributes.Archive))
            {
                return new FileInfo(file.FullName).Length <= 0L;
            }
            return false;
        }

        /// <summary>
        /// 文件是否为空
        /// <para> 文件: 文件大小为0为空</para>
        /// </summary>
        /// <param name="file">文件/目录</param>
        /// <returns>是否为空, 当提供非目录时,返回false</returns>
        public static bool IsEmpty(FileInfo file)
        {
            if (file == null || file.Exists == false)
            {
                return true;
            }
            return file.Length <= 0L;

        }

        /// <summary>
        /// 文件是否为空
        /// <para>目录:里面没有文件时为空</para>
        /// </summary>
        /// <param name="file">目录</param>
        /// <returns></returns>
        public static bool IsEmpty(DirectoryInfo file)
        {
            if (file == null || file.Exists == false)
            {
                return true;
            }

            var subFiles = Directory.GetFileSystemEntries(file.FullName);
            return subFiles.Length == 0;
        }
        /// <summary>
        /// 是否为文件
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public static bool IsFile(FileInfo file)
        {
            if (file == null || file.Exists == false)
            {
                return false;
            }
            return !file.Attributes.HasFlag(FileAttributes.Directory);
        }

        /// <summary>
        /// 是否为文件
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static bool IsFile(string path)
        {
            return IsFile(new FileInfo(path));
        }

        /// <summary>
        /// 是否为文件夹
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public static bool IsDirectory(DirectoryInfo file)
        {
            if (file == null || file.Exists == false)
            {
                return false;
            }
            return file.Attributes.HasFlag(FileAttributes.Directory);
        }

        /// <summary>
        /// 是否为文件夹
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static bool IsDirectory(string path)
        {
            return IsDirectory(new DirectoryInfo(path));
        }

        /// <summary>
        /// 文件是否为非空
        /// <para> 文件: 文件大小不为0为非空</para>
        /// </summary>
        /// <param name="file">文件/目录</param>
        /// <returns></returns>
        public static bool IsNotEmpty(FileInfo file)
        {
            return false == IsEmpty(file);
        }

        /// <summary>
        /// 文件夹是否为非空
        /// <para>目录:里面有文件时为非空</para>
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public static bool IsNotEmpty(DirectoryInfo file)
        {
            return false == IsEmpty(file);
        }

        /// <summary>
        /// 格式化路径
        /// <para>如果同时存在\/ ,替换成一种,去掉重复的</para>
        /// </summary>
        /// <param name="path"></param>
        ///  <param name="replace"></param>
        /// <returns></returns>
        public static string Format(string path, string replace = StrUtil.SLASH)
        {
            // 将所有的反斜杠替换为斜杠
            path = path.Replace("\\", "/");

            // 使用正则表达式将多个斜杠替换为单个斜杠
            path = System.Text.RegularExpressions.Regex.Replace(path, "/+", replace);

            return path;
        }


        /// <summary>
        /// 获得相对子路径，忽略大小写
        /// <list type="table">
        /// <item>dirPath：d:/aaa/bbb   filePath：d:/aaa/bbb/ccc   => ccc</item>
        /// <item>dirPath：d:/Aaa/bbb   filePath：d:/aaa/bbb/ccc.txt   => ccc.txt</item>
        /// <item>dirPath：d:/aaa/bbb   filePath：d:/aaa/bbb/   => ""</item>
        /// </list>
        /// </summary>
        /// <param name="dirPath"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static string SubPath(string dirPath, string filePath)
        {
            if (StrUtil.IsNotEmpty(dirPath) && StrUtil.IsNotEmpty(filePath))
            {
                dirPath = StrUtil.RemoveSuffix(Format(dirPath), StrUtil.SLASH);
                filePath = Format(filePath);

                string result = StrUtil.RemovePrefixIgnoreCase(filePath, dirPath);
                return StrUtil.RemovePrefix(result, StrUtil.SLASH);
            }
            return filePath;
        }

        /// <summary>
        /// 创建目录,失败返回null
        /// </summary>
        /// <param name="file">目录</param>
        /// <returns></returns>
        public static DirectoryInfo Touch(DirectoryInfo file)
        {
            if (file == null) return null;
            if (file.Exists == false)
            {
                try
                {
                    Directory.CreateDirectory(file.FullName);
                }
                catch (Exception)
                {

                    return null;
                }
            }
            return file;
        }

        /// <summary>
        /// 创建文件,失败返回null
        /// </summary>
        /// <param name="file">文件</param>
        /// <returns></returns>
        public static FileInfo Touch(FileInfo file)
        {
            if (file == null) return null;
            if (file.Exists == false)
            {
                try
                {
                    System.IO.File.Create(file.FullName);

                }
                catch (Exception)
                {
                    return null;

                }
            }
            return file;
        }

        /// <summary>
        /// 获取用户路径(绝对路径)
        /// </summary>
        /// <returns></returns>
        public static string GetUserHomePath()
        {
            return Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
        }

        /// <summary>
        /// 指定目录最后修改时间,目录不存在返回null
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public static DateTime? LastModifiedTime(DirectoryInfo file)
        {
            if (false == file.Exists)
            {
                return null;
            }
            return file.LastWriteTime;
        }

        /// <summary>
        /// 指定文件最后修改时间,文件不存在返回null
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public static DateTime? LastModifiedTime(FileInfo file)
        {
            if (false == file.Exists)
            {
                return null;
            }
            return file.LastWriteTime;
        }

        /// <summary>
        /// 清空文件夹
        /// </summary>
        /// <param name="dirPath"></param>
        /// <param name="recursive">是否包含子目录,文件</param>
        /// <returns></returns>
        public static bool Clean(string dirPath, bool recursive = true)
        {
            var dir = new DirectoryInfo(dirPath);
            if (dir.Exists == false) { return false; }
            Directory.Delete(dirPath, recursive);
            return true;
        }

        /// <summary>
        /// 读取文件内容
        /// </summary>
        /// <param name="file"></param>
        /// <param name="charset">字符集</param>
        /// <returns></returns>
        public static string ReadString(FileInfo file, Encoding charset)
        {
            using (StreamReader reader = new StreamReader(file.FullName, charset))
            {
                return reader.ReadToEnd();
            }
            //return System.IO.File.ReadAllText(file.FullName, charset);
        }

        /// <summary>
        /// 读取文件内容
        /// </summary>
        /// <param name="path"></param>
        /// <param name="charset"></param>
        /// <returns></returns>
        public static string ReadString(string path, Encoding charset)
        {
            return ReadString(new FileInfo(path), charset);
        }

        /// <summary>
        /// 读取文件内容
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public static string ReadUtf8String(FileInfo file)
        {
            return ReadString(file, Encoding.UTF8);
        }

        /// <summary>
        /// 读取文件内容
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string ReadUtf8String(String path)
        {
            return ReadString(path, Encoding.UTF8);
        }

        /// <summary>
        /// 读取文件所有数据
        /// </summary>
        /// <param name="file"></param>
        /// <returns>字节码</returns>
        public static byte[] ReadBytes(FileInfo file)
        {

            using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read))
            {
                // 创建一个内存流来保存读取到的字节
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    // 将文件流中的数据复制到内存流中
                    fileStream.CopyTo(memoryStream);
                    // 返回内存流中的字节数组
                    return memoryStream.ToArray();
                }
            }
        }

        /// <summary>
        /// 读取文件所有数据
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns>字节码</returns>
        public static byte[] ReadBytes(String filePath)
        {
            return ReadBytes(new FileInfo(filePath));
        }

        /// <summary>
        /// 将String写入文件，覆盖模式
        /// </summary>
        /// <param name="content"></param>
        /// <param name="file"></param>
        /// <param name="charset"></param>
        /// <returns></returns>
        public static FileInfo WriteString(String content, FileInfo file, Encoding charset)
        {
            using (StreamWriter writer = new StreamWriter(file.FullName, false, charset))
            {
                // 将内容写入文件
                writer.Write(content);
            }
            return file;
        }

        /// <summary>
        /// 将String写入文件，覆盖模式
        /// </summary>
        /// <param name="content"></param>
        /// <param name="path"></param>
        /// <param name="charset"></param>
        /// <returns></returns>

        public static FileInfo WriteString(String content, string path, Encoding charset)
        {
            return WriteString(content, Touch(new FileInfo(path)), charset);
        }

        /// <summary>
        /// 将String写入文件，追加模式
        /// </summary>
        /// <param name="content"></param>
        /// <param name="file"></param>
        /// <param name="charset"></param>
        /// <returns></returns>
        public static FileInfo AppendString(String content, FileInfo file, Encoding charset)
        {
            using (StreamWriter writer = new StreamWriter(file.FullName, false, charset))
            {
                // 将内容写入文件
                writer.Write(content);
            }
            return file;
        }

        /// <summary>
        /// 将String写入文件，UTF-8编码追加模式
        /// </summary>
        /// <param name="content"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        public static FileInfo AppendUtf8String(String content, FileInfo file)
        {
            return AppendString(content, file, Encoding.UTF8);
        }

        /// <summary>
        /// 写入数据到文件
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="dest">目标文件</param>
        /// <param name="off">数据开始位置</param>
        /// <param name="len">数据长度</param>
        /// <param name="isAppend">是否追加模式</param>
        /// <returns></returns>
        public static FileInfo WriteBytes(byte[] data, FileInfo dest, int off, int len, bool isAppend)
        {

            // 判断是否追加模式
            FileMode fileMode = isAppend ? FileMode.Append : FileMode.Create;

            // 使用 FileStream 打开文件
            using (FileStream fs = new FileStream(dest.FullName, fileMode, FileAccess.Write))
            {
                // 将数据写入文件
                fs.Write(data, off, len);
            }
            return new FileInfo(dest.FullName);

        }
        /// <summary>
        /// 获得文件的扩展名（后缀名），扩展名不带“.”
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static String ExtName(String fileName)
        {
            return FileNameUtil.ExtName(fileName);
        }
    }
}